/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.ubinow.mflex.widgets;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import net.ubinow.mflex.baseui.AbsWidget;
import net.ubinow.mflex.baseui.WFont;
import net.ubinow.mflex.data.IDataItem;
import net.ubinow.mflex.data.SimpleDataItem;
import net.ubinow.mflex.util.Constants;
import net.ubinow.mflex.util.MiscUtil;

/**
 *
 * @author Josh
 */
public class WList extends AbsWidget {

    /** horizontal and vertical arrangement of list items **/ 
    public static final int LAYOUT_SCATTERED = 0;
    /** vertical arrangement of list items **/ 
    public static final int LAYOUT_ORDERED   = 1; 
    
    public static final int MODE_EXCLUSIVE   = 0;
    public static final int MODE_MULTIPLE    = 1; 
    
    private Image _iconSelected;
    private Image _icon;
    private int _focusHighlightBgColour = -1;
    private int _selectedHighlightBgColour = -1;
    private WFont _selectedFont;
    private int _listLayout = LAYOUT_SCATTERED;
    private int _selectionMode = MODE_MULTIPLE;
    
    // padding variables
//    private int _textPaddingX = Constants.AD_TEXT_PADDING_X;
//    private int _textPaddingY = Constants.AD_TEXT_PADDING_Y;
    /** the horitontal gap between the icon and text **/ 
    private int _iconPaddingX = 10;
    private int _iconPaddingY = 0;
    private int _itemPaddingX = 10;
    private int _itemPaddingY = Constants.AD_TEXT_PADDING_Y;
    private int _highlightPaddingX = 2;
    private int _highlightPaddingY = 1;
    
    private int _rowHeight = -1; // either set to the largest fonts height or icons height depending on what is higher - set in the resetSize method
    
    private boolean _includeAllOption = false;
    private String _includeAllText = "ALL"; 
    private boolean _includeClearOption = false; 
    private String _includeClearText = "CLEAR";
    
    private MiscUtil _miscUtils = null;
    
    private int _selectionCount = 0;
    
    private WFont _largestFont; // font used to work out the widths and height of this widget
    
    public WList( String id ){
        _id = id; 
        _miscUtils = MiscUtil.getInstance();
        _selectedIndex = -1;
        _paddingW = 5;
    }
                
    //<editor-fold defaultstate="collapsed" desc="AbsWidget abstract methods"> 
    
    protected void setWidgetType() {
        _type = Constants.WIDGET_TYPE_LIST;
    }

    public void setBG(Image bg) {
        System.out.println("Not supported - WList.setBG");
    }

    public void setBG(int colour) {
        System.out.println("Not supported - WList.setBG");
    }

    public void cycle() {
       
    }

    public void paint(Graphics g, int offsetX, int offsetY, int layer) {
        int posX = _x + offsetX;
        int posY = _y + offsetY;
                
        if( _listLayout == LAYOUT_ORDERED ){
            posX += _paddingW;
            
            for( int i=0; i<_itemsCount; i++ ){                                
                
                if( _items[i] == null )
                    continue; 
                
                drawListItem( g, _items[i], (_selectedIndex == i), posX, posY );
                
                posY += _rowHeight;
            }
        }
        else if( _listLayout == LAYOUT_SCATTERED ){
            int workingWidth = _paddingW + posX;
            
            for( int i=0; i<_itemsCount; i++ ){
                if( _items[i] == null )
                    continue; 
                
                int itemWidth = _largestFont.stringWidth( _items[i].getText() );
                itemWidth += _itemPaddingX; 
                
                if( _icon != null ){
                    itemWidth += _icon.getWidth();
                    itemWidth += _iconPaddingX;
                }
                
                // bounds checking
                if( workingWidth + itemWidth > _width ){
                    workingWidth = _paddingW + posX;
                    posY += _rowHeight; 
                    
                    drawListItem( g, _items[i], (_selectedIndex == i), workingWidth, posY );
                    
                    workingWidth += itemWidth;
                }
                else{
                    drawListItem( g, _items[i], (_selectedIndex == i), workingWidth, posY );
                    workingWidth += itemWidth;
                }
            }
        }
    }
    
    private void drawListItem( Graphics g, IDataItem li, boolean isFocused, int x, int y ){                           
        if( li.getFlag() ){
            
            // draw selected icon            
            if( _iconSelected != null ){
                g.drawImage( _iconSelected, x, y+_iconPaddingY, Constants.GFX_ALIGN_TOP_LEFT );            
                x += _iconPaddingX + _iconSelected.getWidth();
            }
            
            // draw selected highlight
            if( _selectedHighlightBgColour != -1 ){
                g.setColor( _selectedHighlightBgColour );
                g.fillRect( x-_highlightPaddingX, y-_highlightPaddingY, 
                        _selectedFont.stringWidth( li.getText() ) + _highlightPaddingX, _selectedFont.getHeight() + _highlightPaddingY );
            }
        }
        else if( _icon != null ){
            // draw icon 
            g.drawImage( _icon, x, y+_iconPaddingY, Constants.GFX_ALIGN_TOP_LEFT );
            x += _iconPaddingX + _icon.getWidth();
        }
        
        if( isFocused ){
            // draw focus highlight
            if( _focusHighlightBgColour != -1 ){
                g.setColor( _focusHighlightBgColour );
                g.fillRect( x-_highlightPaddingX, y-_highlightPaddingY, 
                        _selectedFont.stringWidth( li.getText() ) + _highlightPaddingX, _selectedFont.getHeight() + _highlightPaddingY );
            }
        }
               
        // draw text
        if( li.getFlag() ){
            _selectedFont.drawString( g, li.getText(), x, y );
        }
        else{
            _font.drawString( g, li.getText(), x, y );
        }
        
    }

    public boolean handleKeyPressed(int action, int keyCode) {
        if( action == Canvas.LEFT ){
            _selectedIndex--;
            if( _selectedIndex < 0 )
                _selectedIndex = _itemsCount-1;
            
            return true; 
        }
        else if( action == Canvas.RIGHT ){
            _selectedIndex++;
            if( _selectedIndex >= _itemsCount )
                _selectedIndex = 0;
            
            return true; 
        }
        else if( action == Canvas.FIRE ){
            if( _selectedIndex >= 0 && _selectedIndex < _itemsCount && _items[_selectedIndex] != null ){
                if( _selectionMode == MODE_EXCLUSIVE && !_items[_selectedIndex].getFlag() ){
                    unselectAll(); 
                }
                
                if( _items[_selectedIndex].getText().equals( _includeAllText ) ){
                    selectAll();
                }
                else if( _items[_selectedIndex].getText().equals( _includeClearText ) ){
                    unselectAll();
                }
                else{                
                    _items[_selectedIndex].setFlag( !_items[_selectedIndex].getFlag() );

                    if( _items[_selectedIndex].getFlag() )
                        _selectionCount++;
                    else
                        _selectionCount--;
                }
                
                return true;
            }
        }
        else if( _listLayout == LAYOUT_ORDERED ){
            if( action == Canvas.UP ){
                _selectedIndex--;
                if( _selectedIndex >= 0 )
                    return true;
                else
                    return false; 
            }
            else if( action == Canvas.DOWN ){
                _selectedIndex++; 
                if( _selectedIndex < _itemsCount )
                    return true;
                else{
                    _selectedIndex = -1;
                    return false; 
                }
            }
        }
        
        return false; 
    }        

    public boolean handleKeyReleased(int action, int keyCode) {
        return false; 
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="overrides">
    
    public void setFocus( boolean focus, int direction ){
        super.setFocus(focus, direction);
        if( !focus ){
            _selectedIndex = -1;
        }
        else{
            _selectedIndex = 0;
        }
    }
    
    public void setItems( IDataItem[] items ){
        super.setItems(items);        
        
        if( _includeAllOption )
            super.insertItem( 0, new SimpleDataItem( _includeAllText ) );
        
        if( _includeClearOption )
            super.addItem( new SimpleDataItem( _includeClearText ) );
        
        resetSize();
    }
    
    public void addItem( IDataItem item ){
        if( _includeClearOption && !item.getText().equals( _includeClearText ) )
            super.insertItem( _itemsCount-1, item );
        else
            super.addItem(item);
        resetSize();
    }
    
    public void insertItem( int index, IDataItem item ){
        super.insertItem(index, item);
        resetSize();
    }
    
    public void removeItem( IDataItem item ){
        super.removeItem(item);
        resetSize();
    }        
    
    public void setFont( WFont font ){
        super.setFont( font );
        resetLargestFont();         
    }
    
    public void setWidth( int width ){
        super.setWidth( width );
        resetLargestFont();
    }
    
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="getters and setters">
    
    public IDataItem[] getSelectedItems(){
        if( _selectionCount == 0 || _items == null || _itemsCount <= 0 )
            return null;
        
        IDataItem[] selItems = new IDataItem[_selectionCount];
        int index = 0;
        for( int i=0; i<_itemsCount; i++ ){
            if( _items[i] == null )
                continue; 
            
            selItems[index] = _items[i]; 
            index++; 
        }
        
        return selItems;
    }
    
    public void setIcons( Image icon, Image iconSelected ){
        _icon = icon; 
        _iconSelected = iconSelected;
    }
    
    public Image getIconSelected() {
        return _iconSelected;
    }

    public void setIconSelected(Image iconSelected) {
        this._iconSelected = iconSelected;
    }

    public Image getIcon() {
        return _icon;
    }

    public void setIcon(Image icon) {
        this._icon = icon;
        resetRowHeight();
    }

    public int getFocusHighlightBgColour() {
        return _focusHighlightBgColour;
    }

    public void setFocusHighlightBgColour(int focusHighlightBgColour) {
        this._focusHighlightBgColour = focusHighlightBgColour;
    }

    public int getSelectedHighlightBgColour() {
        return _selectedHighlightBgColour;
    }

    public void setSelectedHighlightBgColour(int selectedHighlightBgColour) {
        this._selectedHighlightBgColour = selectedHighlightBgColour;
    }

    public WFont getSelectedFont() {
        return _selectedFont;
    }

    public void setSelectedFont(WFont selectedFont) {
        this._selectedFont = selectedFont;
        resetLargestFont();  
    }

    public int getListLayout() {
        return _listLayout;
    }

    public void setListLayout(int listLayout) {
        this._listLayout = listLayout;
    }

    public int getSelectionMode() {
        return _selectionMode;
    }

    public void setSelectionMode(int selectionMode) {
        this._selectionMode = selectionMode;
    }
    
//    public int getTextPaddingX() {
//        return _textPaddingX;
//    }
//
//    public void setTextPaddingX(int textPaddingX) {
//        this._textPaddingX = textPaddingX;
//    }
//
//
//    public int getTextPaddingY() {
//        return _textPaddingY;
//    }
//
//    public void setTextPaddingY(int textPaddingY) {
//        this._textPaddingY = textPaddingY;
//    }


    /** the horitontal gap between the icon and text **/
    public int getIconPaddingX() {
        return _iconPaddingX;
    }

    /** the horitontal gap between the icon and text **/
    public void setIconPaddingX(int iconPaddingX) {
        this._iconPaddingX = iconPaddingX;
    }


    public int getIconPaddingY() {
        return _iconPaddingY;
    }

    public void setIconPaddingY(int iconPaddingY) {
        this._iconPaddingY = iconPaddingY;
    }


    public int getItemPaddingX() {
        return _itemPaddingX;
    }

    public void setItemPaddingX(int itemPaddingX) {
        this._itemPaddingX = itemPaddingX;
    }


    public int getItemPaddingY() {
        return _itemPaddingY;
    }

    public void setItemPaddingY(int itemPaddingY) {
        this._itemPaddingY = itemPaddingY;
    }


    public boolean isIncludeAllOption() {
        return _includeAllOption;
    }

    public void setIncludeAllOption(boolean includeAllOption) {
        this._includeAllOption = includeAllOption;
        
        if( _includeAllOption ){
            insertItem( 0, new SimpleDataItem( _includeAllText ) );
        }
        else{
            removeItem( _items[0] );
        }
    }

    public void setIncludeAllText( String text ){
        _includeAllText = text;
    }

    public boolean isIncludeClearOption() {
        return _includeClearOption;
    }

    public void setIncludeClearOption(boolean includeClearOption) {
        this._includeClearOption = includeClearOption;
        
        if( _includeClearOption )
            addItem( new SimpleDataItem( _includeClearText ) );
        else
            removeItem( _items[_itemsCount-1] );
    }
    
    public void setIncludeClearText( String text ){
        _includeClearText = text;
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="private helper methods">        
    
    private void unselectAll(){
        for( int i=_itemsCount-1; i>=0; i-- ){
            if( _items[i] == null || _items[i].getText().equals( _includeAllText ) || _items[i].getText().equals( _includeClearText ) )
                continue; 
            _items[i].setFlag( false );
        }
    }
    
    private void selectAll(){
        for( int i=_itemsCount-1; i>=0; i-- ){
            if( _items[i] == null || _items[i].getText().equals( _includeAllText ) || _items[i].getText().equals( _includeClearText ) )
                continue; 
            _items[i].setFlag( true );
        }
    }
    
    private void resetLargestFont(){
        if( _selectedFont != null && _font != null ){
            if( _selectedFont.getHeight() > _font.getHeight() )
                _largestFont = _selectedFont;
            else
                _largestFont = _font;
        }
        else if( _selectedFont == null && _font != null ){
            _largestFont = _font; 
        }
        else if( _font == null && _selectedFont != null ){
            _largestFont = _selectedFont;
        }
        else{
            _largestFont = null;
        }
        
        resetRowHeight();
    }        
    
    private void resetSize(){
        if( _largestFont == null )
            return; 
        
        resetRowHeight();;
        
        if( !_focus )
            _selectedIndex = -1;
        
        if( _listLayout == LAYOUT_ORDERED ){
            if( _itemsCount > 0 ){               
                int paddingY = _largestFont.getHeight();
                if( _icon != null && _iconPaddingY > paddingY )
                    paddingY = _iconPaddingY;
                
                setHeight( (_rowHeight * _itemsCount) - paddingY );
            }
            else{
                setHeight( 0 );
            }
        }
        else if( _listLayout == LAYOUT_SCATTERED ) {
            int _workingWidth = _paddingW;
            
            if( _itemsCount > 0 )
                setHeight( _rowHeight );
            
            for( int i=0; i<_itemsCount; i++ ){
                if( _items[i] == null )
                    continue; 
                
                int itemWidth = _largestFont.stringWidth( _items[i].getText() );
                itemWidth += _itemPaddingX; 
                
                if( _icon != null ){
                    itemWidth += _icon.getWidth();
                    itemWidth += _iconPaddingX;
                }
                
                // bounds checking
                if( _workingWidth + itemWidth > _width ){
                    _workingWidth = itemWidth + _paddingW;
                    setHeight( _height + _rowHeight ); 
                }
                else{
                    _workingWidth += itemWidth;
                }
            }
        }
    }
    
    private void resetRowHeight(){
        if( _largestFont == null )
            return;
        
        _rowHeight = _largestFont.getHeight();
                
        if( _icon != null && _icon.getHeight() > _rowHeight ){
            _rowHeight = _icon.getHeight();
            if( _iconPaddingY > _itemPaddingY )
                _rowHeight += _iconPaddingY;
            else
                _rowHeight += _itemPaddingY;            
        }
        else{
            _rowHeight += _itemPaddingY;            
        }                
    }
    
    //</editor-fold>
}
